﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Kenly.ChineseSegment.Core
{
    /// <summary>
    /// 
    /// </summary>
    public static class Training
    {
        //public static List<string> Train(string text)
        //{
        //    return new List<string>();
        //}


        /// <summary>
        /// 
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static List<WordFrequence> RecognizeWords(string text)
        {
            List<WordFrequence> finalWords = new List<WordFrequence>();
            if (string.IsNullOrEmpty(text))
            {
                return finalWords;
            }

            List<string> twoCharWords = new List<string>();
            string[] sentences = TextProcess.SplitSentences(text);

            Dictionary<string, WordFrequence> twoCharWordsFrequences = RecognizeTwoCharWords(sentences);
            Dictionary<string, WordFrequence> newTwoCharWordsFrequences = new Dictionary<string, WordFrequence>();
            Dictionary<string, WordFrequence> newWordsFrequences = new Dictionary<string, WordFrequence>();

            FilterTwoCharWordsFrequences(ref twoCharWords, twoCharWordsFrequences);

            Dictionary<string, WordFrequence> wordsFrequences = new Dictionary<string, WordFrequence>();
            StringBuilder lastWordsBuffer = new StringBuilder();

            for (int i = 0; i < twoCharWords.Count - 1; i++)
            {
                WordFrequence currentFrequence = twoCharWordsFrequences[twoCharWords[i]];
                WordFrequence nextFrequence = twoCharWordsFrequences[twoCharWords[i + 1]];

                MergeWords(currentFrequence, nextFrequence, ref i, ref newTwoCharWordsFrequences);
            }

            for (int i = 0; i < newTwoCharWordsFrequences.Count - 1; i++)
            {
                WordFrequence currentFrequence = twoCharWordsFrequences[twoCharWords[i]];
                WordFrequence nextFrequence = twoCharWordsFrequences[twoCharWords[i + 1]];

                MergeWords(currentFrequence, nextFrequence, ref i, ref newWordsFrequences);
            }
            finalWords.AddRange(newWordsFrequences.Values);

            return finalWords;
        }

        private static void MergeWords(WordFrequence currentFrequence, WordFrequence nextFrequence, 
            ref int newIndex, ref Dictionary<string, WordFrequence>  newWordsFrequences)
        {
            if (AreSibling(currentFrequence, nextFrequence))
            {
                 currentFrequence.Word = currentFrequence.Word + nextFrequence.Word;
                 newWordsFrequences.Add(currentFrequence.Word, currentFrequence);
                 newIndex++;
            }
            else
            {
                 newWordsFrequences.Add(currentFrequence.Word, currentFrequence);
            }
        }

        private static bool AreSibling(WordFrequence currentFrequence, WordFrequence nextFrequence)
        {
            if (currentFrequence.SentenceIndex == nextFrequence.SentenceIndex &&
                (currentFrequence.Index + currentFrequence.Word.Length) == nextFrequence.Index)
            {
                return true;
            }

            return false;
        }

        private static void FilterTwoCharWordsFrequences(ref List<string> words,
            Dictionary<string, WordFrequence> twoCharWordsFrequences)
        {
            foreach (string key in twoCharWordsFrequences.Keys)
            {
                if (twoCharWordsFrequences[key].Frequence > 1)
                {
                    words.Add(twoCharWordsFrequences[key].Word);
                }
            }
        }

        private static Dictionary<string, WordFrequence> RecognizeTwoCharWords(string[] sentences)
        {
            Dictionary<string, WordFrequence> wordFrequences = new Dictionary<string, WordFrequence>();
            if (sentences == null || sentences.Length <= 0)
            {
                return wordFrequences;
            }

            for (int i = 0; i < sentences.Length; i++)
            {
                RecognizeTwoCharWordsInSentence(sentences[i].Trim(), i, ref wordFrequences);
            }

            return wordFrequences;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="text"></param>
        /// <param name="words"></param>
        private static void RecognizeTwoCharWordsInSentence(string sentence, int sentenceIndex,
            ref Dictionary<string, WordFrequence> wordFrequences)
        {
            char[] chars = sentence.ToCharArray();

            for (int i = 0; i < chars.Length - 1; i++)
            {
                string twoChars = chars[i].ToString() + chars[i + 1].ToString();
                if (!wordFrequences.ContainsKey(twoChars))
                {
                    WordFrequence frequence = CreateNewFrequence(sentenceIndex, i, twoChars);
                    wordFrequences.Add(twoChars, frequence);
                }
                else
                {
                    wordFrequences[twoChars].Frequence = wordFrequences[twoChars].Frequence + 1;
                    i++;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sentenceIndex"></param>
        /// <param name="index"></param>
        /// <param name="twoChars"></param>
        /// <returns></returns>
        private static WordFrequence CreateNewFrequence(int sentenceIndex, int index, string twoChars)
        {
            WordFrequence frequence = new WordFrequence();
            frequence.Word = twoChars;
            frequence.SentenceIndex = sentenceIndex;
            frequence.Index = index;
            frequence.Frequence = 1;
            return frequence;
        }
    }
}
